import { IPSAppView } from "@ibiz/dynamic-model-api";
import { AppServiceBase, GetModelService, Http, Util } from "ibiz-core";
import { NoticeHandler } from "ibiz-vue";
import { clearCookie, getCookie } from "qx-util";
import { AuthGuardBase } from "./auth-guard";

/**
 * @description 本地AuthGuard对象
 * @export
 * @class LocalAuthGuard
 */
export class LocalAuthGuard extends AuthGuardBase {

  /**
   * @description 本地AuthGuard对象唯一实例
   * @static
   * @type {LocalAuthGuard}
   * @memberof LocalAuthGuard
   */
  static instance: LocalAuthGuard;

  /**
   * @description 获取本地AuthGuard对象
   * @static
   * @return {*}  {LocalAuthGuard}
   * @memberof LocalAuthGuard
   */
  static getInstance(): LocalAuthGuard {
    if (!this.instance) {
      this.instance = new LocalAuthGuard();
    }
    return this.instance;
  }

  /**
   * @description 权限校验
   * @param {*} router
   * @return {*} 
   * @memberof LocalAuthGuard
   */
  async authGuard(router: any, hooks: any): Promise<boolean | undefined> {  
    if (AppServiceBase.getInstance().getAppEnvironment() && AppServiceBase.getInstance().getAppEnvironment().SaaSMode) {
      //  TODO SaasMode支持
      return await this.getAppData(router);
    } else {
      return await this.getAppData(router);
    }
  }

  /**
   * @description 获取应用数据
   * @private
   * @param {*} router
   * @memberof LocalAuthGuard
   */
  private async getAppData(router: any) {
    let flag: boolean = true;
    let data: any = {};
    if (getCookie('ibzuaa-user')) {
      let user: any = JSON.parse(getCookie('ibzuaa-user') as string);
      let localAppData: any = {};
      if (user.sessionParams) {
        localAppData = { context: user.sessionParams };
        Object.assign(localAppData, data);
      }
      data = JSON.parse(JSON.stringify(localAppData));
    } else {
      flag = false;
    }
    if (localStorage.getItem('localdata')) {
      router.app.$store.commit(
        'addLocalData',
        JSON.parse(localStorage.getItem('localdata') as string),
      );
    }
    router.app.$store.commit('addAppData', data);
    // 提交统一资源数据
    router.app.$store.dispatch('authresource/commitAuthData', data);
    await this.initAppService(router);
    if (!flag) {
      const result = await this.doNoLogin(router, "登录失败，请联系管理员");
      return result;
    }
    await this.initAppService(router);
    return true;
  }

  private async doNoLogin(router: any, message: string) {
    const gotoLogin: Function = () => {
      this.clearAppData(router.app.$store);
      if (AppServiceBase.getInstance().getAppEnvironment()?.LoginUrl) {
        window.location.href = `${AppServiceBase.getInstance().getAppEnvironment().LoginUrl}?redirect=${window.location.href}`;
      } else {
        if (Object.is(router.currentRoute.name, 'login')) {
          NoticeHandler.errorHandler(message);
          return;
        }
        router.push({ name: 'login', query: { redirect: window.location.hash.replace("#", '') } });
      }
      return false;
    }
    return this.handleAccUserMode(router, gotoLogin);
  }

  /**
   * 处理用户范围模式（0：未指定、 2：登录用户、 3：匿名用户及登录用户、 4：登录用户且拥有指定资源能力 ）
   *
   * @memberof RemoteAuthGuard
   */
  private async handleAccUserMode(router: any, gotoLogin: Function) {
    try {
      const activedPath: string = window.location.hash.substr(1);
      let activedRoute: any = router.getRoutes().find((item: any) => {
        return item.regex.test(activedPath);
      })
      if (activedRoute) {
        // 跳转应用首页视图
        if (activedRoute.redirect) {
          activedRoute = router.getRoutes().find((item: any) => {
            return item.meta.viewType === 'APPINDEX';
          })
          if (activedRoute && activedRoute.meta) {
            if (activedRoute.meta.requireAuth) {
              gotoLogin();
            } else {
              return true;
            }
          }
        } else {
          // 自定义视图路径跳转
          const dynaModelFilePath: string = await this.computeActivedViewFilePath(activedPath, activedRoute)
          if (dynaModelFilePath) {
            const modeldata = await ((await GetModelService()).getPSAppView(dynaModelFilePath)) as IPSAppView;
            if ((modeldata.accUserMode === 0) || (modeldata.accUserMode === 3)) {
              return true;
            } else {
              gotoLogin();
            }
          } else {
            gotoLogin();
          }
        }
      } else {
        gotoLogin();
      }
    } catch (error) {
      gotoLogin();
    }
  }

  private async computeActivedViewFilePath(activedPath: string, route: any) {
    if (route && route.meta && route.meta.parameters) {
      let resource: string = route.meta.resource ? route.meta.resource.toLowerCase() : '';
      let activedView: any = route.meta.parameters.find((item: any) => {
        return item.pathName === 'views';
      });
      let localActivedView: any = Util.deepCopy(activedView);
      if (Object.is(localActivedView.parameterName, 'view') && Object.is(localActivedView.pathName, 'views')) {
        localActivedView.parameterName = this.parseUrlDynamicParam(activedPath, route).view;
      }
      if (localActivedView && localActivedView.parameterName) {
        const path = (await GetModelService()).getPSAppViewPath(`${resource}${localActivedView.parameterName}`);
        return path;
      } else {
        return '';
      }
    } else {
      return '';
    }
  }

  private parseUrlDynamicParam(activedPath: string, route: any): any {
    const keys: Array<any> = route.regex.keys;
    const matchArray = route.regex.exec(activedPath);
    let tempValue: Object = {};
    keys.forEach((item: any, index: number) => {
      if (matchArray[index + 1]) {
        Object.defineProperty(tempValue, item.name, {
          enumerable: true,
          value: decodeURIComponent(matchArray[index + 1])
        });
      }
    });
    return tempValue;
  }

  private clearAppData(store: any) {
    // 清除user、token
    clearCookie('ibzuaa-token', true);
    clearCookie('ibzuaa-expired', true);
    clearCookie('ibzuaa-user', true);
    // 清除应用级数据
    localStorage.removeItem('localdata')
    store.commit('addAppData', {});
    store.dispatch('authresource/commitAuthData', {});
  }
}